%{
	#include <stdio.h>
	#include "datatypes.h"
	#include "globals.h"
	#include "internal_kb.h"
	#include "limits.h"
	#include "print_utils.h"
	#define YYSTYPE Expression
	int yylex(void);
	int yylineno;
	void yyerror(char *);
	FILE *yyin; 		/* Input for yacc parser. */
	int cls_exp_count;	/* number of conjuncts for conjunction */
	Concept* cls_exps[MAX_CONJUNCT_COUNT]; /* conjuncts */

	int alternation_stack[MAX_CONJ_EXISTS_ALTERNATION];
	int alternation_count = 0;
	enum concept_description_type parent_expression;
%}

%token PREFIX ONTOLOGY IMPORT BASEIRI FULLIRI
%token IDENTIFIER OBJECTSOMEVALUESFROM OBJECTINTERSECTIONOF DECLARATION CLASS
%token OBJECTPROPERTY 
%token EQUIVALENTCLASSES SUBCLASSOF 

%%

ontologyDocument:
	prefixDeclaration ontology
	;
prefixDeclaration:
	| prefixDeclaration PREFIX '(' prefixName ':' '=' BASEIRI ')' 
	;

prefixName:
	IDENTIFIER
	;

ontology:
	ONTOLOGY '(' BASEIRI axioms ')' 
	;

axiom:
	classAxiom
	;

 /* 5.8  Entity Declarations and Typing */
 // Declarations are ignored by the lexical analyzer since they are irrelevant
 // for reasoning
 // declaration:
 // 	DECLARATION '(' entity ')'
 //	;
 // entity:
 // 	CLASS '(' class ')' | OBJECTPROPERTY '(' objectProperty ')'
 // 	;

classAxiom:
	subClassAxiom
	| equivalentClassAxiom
	;
axioms:
	axiom
	| axioms axiom
	;


subClassAxiom:
	SUBCLASSOF '(' classExpression classExpression ')'	{
		// subclass_axs[subclass_ax_count] = create_subclass_axiom($3.concept,$4.concept);
		tbox.axioms[tbox.axiom_count] = create_subclass_axiom($3.concept,$4.concept);
		++tbox.axiom_count;
		++subclass_ax_count;
	}
	;

equivalentClassAxiom:
	EQUIVALENTCLASSES '(' classExpression classExpression ')' {
		// eqclass_axs[eqclass_ax_count] = create_eqclass_axiom($3.concept,$4.concept);
		tbox.axioms[tbox.axiom_count] = create_eqclass_axiom($3.concept,$4.concept);
		++tbox.axiom_count;
		++eqclass_ax_count;
	}
	;

	/* TODO: add TOP! */
class:
	FULLIRI
	;

classExpression:
	class			{ $$.concept = $1.concept; }
	| objectIntersectionOf  { $$.concept = $1.concept; }
	| objectSomeValuesFrom  { $$.concept = $1.concept; }
	;
	
	
objectIntersectionOf:
	OBJECTINTERSECTIONOF '(' classExpression classExpression classExpressions ')'				{
				 // $$.concept = create_conjunction($3.concept,$4.concept);
if ($$.concept != NULL) 
printf("parse stack top: %d\n", $$.concept->type);
printf("(y1)object_intersection\n");

printf("(y1)alternation_count:%d\n",alternation_count);
printf("(y1)alternation stack top:%d\n",alternation_stack[alternation_count]);
printf("(y1)parent expression:%d\n",parent_expression);
fflush(stdout);
				 if (alternation_stack[alternation_count] == 1) {
					// if we are in the first conjunction
					if ($3.concept != NULL)
				 		cls_exps[cls_exp_count++] = $3.concept;
					if ($4.concept != NULL)
				 		cls_exps[cls_exp_count++] = $4.concept;
				 	$$.concept = create_conjunction(cls_exp_count,cls_exps);
				 	cls_exp_count = 0;
					// nesting_depth = 0;
					alternation_stack[alternation_count] = 0;
					// if (expression_stack[expression_depth] == EXISTENTIAL_RESTRICTION)
				// 		--alternation_count;
				 }
				 else {
					// if we are in a nested conjunction
					// retun NULL to the upper level, add
					// conjuncts to cls_exps
				 	cls_exps[cls_exp_count++] = $3.concept;
				 	cls_exps[cls_exp_count++] = $4.concept;
					$$.concept = NULL;
					// --nesting_depth;
					--alternation_stack[alternation_count];
				 }
printf("(y2)alternation_count:%d\n",alternation_count);
printf("(y2)alternation stack top:%d\n",alternation_stack[alternation_count]);
fflush(stdout);
				 // last_expression = CONJUNCTION;
				}
	;

objectSomeValuesFrom:
	OBJECTSOMEVALUESFROM '(' objectPropertyExpression classExpression ')' {
printf("(y)object_some_values_from\n");
				 $$.concept = create_exists($3.role,$4.concept);
				 // last_expression = EXISTENTIAL_RESTRICTION;
				}
	;

objectPropertyExpression:
	objectProperty 
	;

 /* 5.3 Object Properties */
objectProperty:
	FULLIRI
	;

classExpressions:
	| 
	classExpressions classExpression {
		if ($2.concept != NULL)
			cls_exps[cls_exp_count++] = $2.concept;
	}
	;
	

%%

void yyerror(char *s) {
	fprintf(stderr, "\nline %d: %s\n", yylineno, s);
}
